﻿//#define _CRT_SECURE_NO_WARNINGS
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>

#include "common.h"

void test_pointer()
{
	char* p1 = "hello"; // 字符串常量，在内存中只存一次
	char* p2 = "hello";

	char arr1[] = "hello"; // 字符串字面值，在内存中存两次
	char arr2[] = "hello";

	printf("p1 == p2: %d\n", p1 == p2); // 1
	printf("arr1 == arr2: %d\n", arr2 == arr1); // 0

	arr2[0] = 'P';  // 修改 arr2 的值
	printf("arr1: %s\n", arr1); // hello
	printf("arr2: %s\n", arr2); // Pello
}

int bubble_sort_int(int arr[], int n)
{ // 冒泡排序，只能排序 int 数组
	int i, j, temp, count = 0;
	for (i = 0; i < n - 1; ++i)
	{
		int flag = 0;
		for (j = 0; j < n - 1 - i; ++j)
			if (arr[j] > arr[j + 1])
			{
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
				flag = 1; // 发生交换
				++count;
			}
		if (!flag)
			break; // 若没有交换，说明已经排序好了，可以退出循环
	}
}

int int_cmp_reverse(const void* a, const  void* b)//自定义比较函数，用于降序排序 int 数组
{
	return *(int*)b - *(int*)a;
}

struct Stu { // 结构体
	int age;
	char name[20];
	float score;
};

int struct_cmp_score(const void* a, const void* b) // 自定义比较函数，用于排序结构体数组
{ // 按照 score 升序排序
	if (((struct Stu*)a)->score > ((struct Stu*)b)->score)
		return 1;
	else if (((struct Stu*)a)->score < ((struct Stu*)b)->score)
		return -1;
	else
		return 0;
}

int struct_cmp_name_reverse(const void* a, const void* b)
{ // 按照 name 降序排序
	// strcmp(a, b) ----> >0 表示 a > b，<0 表示 a < b，=0 表示 a == b
	return strcmp(((struct Stu*)b)->name, ((struct Stu*)a)->name);
}

struct Stu stu1 = { 26, "Tom", 85.5 };
struct Stu stu2 = { 25, "Jerry", 92.0 };
struct Stu stu3 = { 18, "Mike", 78.5 };
struct Stu stu4 = { 24, "Lily", 88.0 };
struct Stu stu5 = { 23, "Lucy", 90.0 };

void test_struct_cmp()
{
	struct Stu arr1[] = { stu1, stu2, stu3, stu4, stu5 }; // 结构体数组
	qsort(arr1, 5, sizeof(struct Stu), struct_cmp_score); // 排序
	printf("结构体类型 Stu 按照 score 排序结果：\n");
	for (int i = 0; i < 5; ++i)
		printf("%d %s %.1f\n", arr1[i].age, arr1[i].name, arr1[i].score);

	stu1.score = 80.0; // 修改 stu1 的分数
	printf("stu1.score = %.1f\n", stu1.score);
	qsort(arr1, 5, sizeof(struct Stu), struct_cmp_name_reverse); // 排序
	printf("结构体类型 Stu 按照 name 降序排序结果：\n");
	for (int i = 0; i < 5; ++i) // Tom 的 score 为原值 85.5，说明结构体数组是拷贝数据
		printf("%d %s %.1f\n", arr1[i].age, arr1[i].name, arr1[i].score);
}

//void swap_self(char* elem1, char* elem2, int width) // 交换函数
//{
//	int i;
//	char temp;
//	for (i = 0; i < width; ++i)
//	{
//		temp = elem1[i];
//		elem1[i] = elem2[i];
//		elem2[i] = temp;
//	}
//}

//typedef unsigned int size_t; // 定义 size_t 类型（头文件 <vcruntime.h> 中已有定义）
int bubble_sort_more(void* base, size_t num, size_t width,
	int(__cdecl* compare)(const void* elem1, const void* elem2))
{ // 冒泡排序，可以排序多种类型的数组，返回排序数组交换次数
	int i, j, count = 0;
	char temp;
	for (i = 0; i < num - 1; ++i)
	{
		int flag = 0;
		for (j = 0; j < num - 1 - i; ++j)
			if (compare((char*)base + j * width,
				(char*)base + (j + 1) * width) > 0)
			{
				//swap_self(((char*)base) + j * width,
				//	((char*)base) + (j + 1) * width, width); // 交换函数
				int k;
				for (k = 0; k < width; ++k)
				{ // 不写交换函数实现交换
					temp = ((char*)base)[j * width + k];
					((char*)base)[j * width + k] =
						((char*)base)[(j + 1) * width + k];
					((char*)base)[(j + 1) * width + k] = temp;
				}
				flag = 1; // 发生交换
				++count;
			}
		if (!flag)
			break; // 若没有交换，说明已经排序好了，可以退出循环
	}
}

int cmp_char(const void* elem1, const void* elem2)
{ // 自定义比较函数，用于 char 数组排序
	return *(char*)elem1 - *(char*)elem2;
}

int cmp_struct_name(const void* elem1, const void* elem2)
{ // 自定义比较函数，用于 Stu 结构体数组排序，按照 name 排序
	return strcmp(((struct Stu*)elem1)->name, ((struct Stu*)elem2)->name);
}

void bubble_sort_more_test()
{ // 冒泡排序排序多种数组测试
	// 排序 char 数组
	char arr1[10] = { 'i', 'a', 'g', 'b', 'c', 'd', 'f', 'e', 'h', 'j' };
	int sz = sizeof(arr1) / sizeof(arr1[0]); // 计算数组元素个数
	bubble_sort_more(arr1, sz, sizeof(char), cmp_char); // 降序排序
	//printf("字符降序排序结果：%s\n", arr1); // 后面没有 '\0' 结尾，后面会有随机 烫烫烫 
	printf("字符降序排序结果：");
	int i;
	for (i = 0; i < sz; ++i)
		printf("%c ", arr1[i]);
	printf("\n");

	// 排序 Stu 结构体数组
	struct Stu arr2[] = { stu1, stu2, stu3, stu4, stu5 }; // 结构体数组
	sz = sizeof(arr2) / sizeof(arr2[0]); // 计算数组元素个数
	bubble_sort_more(arr2, sz, sizeof(struct Stu), struct_cmp_score);
	// 按照 score 升序排序
	printf("结构体类型 Stu 按照 score 排序结果：\n");
	for (i = 0; i < sz; ++i)
		printf("%d %s %.1f\n", arr2[i].age, arr2[i].name, arr2[i].score);

	// 按照 name 排序
	bubble_sort_more(arr2, sz, sizeof(struct Stu), cmp_struct_name);
	printf("结构体类型 Stu 按照 name 排序结果：\n");
	for (i = 0; i < sz; ++i) // Tom 的 score 为原值 85.5，说明结构体数组是拷贝数据
		printf("%d %s %.1f\n", arr2[i].age, arr2[i].name, arr2[i].score);
}
